package com.jackykeke.opengldemo.renderer.circle;

import android.opengl.GLES20;
import android.opengl.GLES30;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.util.Log;

import com.jackykeke.opengldemo.R;
import com.jackykeke.opengldemo.utils.ResReadUtil;
import com.jackykeke.opengldemo.utils.ShaderUtil;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class ConeRenderer implements GLSurfaceView.Renderer {


    private final FloatBuffer vertexBuffer;
    private Float height = 0.3f;//z轴高度
    private int n = 360;
    private double radius = 0.5;//半径
    private int aPositionLocation;


    private static int POSITION_COMPONENT_COUNT = 3;
    //    private static int COLOR_COMPONENT_COUNT = 3;
    private static final int BYTES_PER_FLOAT = 4;
    //之前定义的坐标数据中，每一行是5个数据，前两个表示坐标(x,y)，后三个表示颜色(r,g,b)
    private static final int STRIDE = (POSITION_COMPONENT_COUNT /*+ COLOR_COMPONENT_COUNT*/) * BYTES_PER_FLOAT;


    //圆锥求顶点
    // OpenGL ES3.0中物体的绘制重点就是在于把这个物体表面分解成三角形，
    // 分解成功后，绘制自然就不成问题了。圆锥我们很容易就能想到把它拆解成一个圆形和一个锥面，
    // 锥面的顶点与圆形的顶点，除了锥面的中心点的坐标有了“高度”，
    private float[] createPositions() {
        ArrayList<Float> data = new ArrayList<>();
        //设置圆心坐标
        data.add(0.0f);
        data.add(0.0f);
        data.add(height);

        float angDegSpan = 360f / n;
        for (float i = 0; i < 360 + angDegSpan; i += angDegSpan) {
            data.add((float) (radius * Math.sin(i * Math.PI / 180f)));
            data.add((float) (radius * Math.cos(i * Math.PI / 180f)));
            data.add(0.0f);
        }


        float[] f = new float[data.size()];
        Log.d("TAG", "data.size() 为" + data.size());
        for (int i = 0; i < f.length; i++) {
            f[i] = data.get(i);
        }
        return f;



    }

    float[] floats = createPositions();

    public ConeRenderer() {


        //分配内存空间,每个浮点型占4字节空间
        vertexBuffer = ByteBuffer.allocateDirect(floats.length * 4)
                .order(ByteOrder.nativeOrder())
                //传入指定的坐标数据
                .asFloatBuffer().put(floats);

        vertexBuffer.position(0);
    }

    int mProgram;

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        GLES30.glEnable(GLES30.GL_DEPTH_TEST);
        GLES30.glClearColor(0.5f, 0.5f, 0.5f, 0.5f);

        //编译
        int vertexShaderId = ShaderUtil.compileVertexShader(ResReadUtil.readResource(R.raw.circle_vertex_shader));
        int fragmentShaderId = ShaderUtil.compileFragmentShader(ResReadUtil.readResource(R.raw.circle_fragment_shader));

        //连接程序片段
        mProgram = ShaderUtil.linkProgram(vertexShaderId, fragmentShaderId);

    }

    private float mMatrix[] = new float[16];


    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        GLES30.glViewport(0, 0, width, height);

        final float aspectRatio = width > height ? (float) width / (float) height : (float) height / (float) width;

        if (width > height) {
            Matrix.orthoM(mMatrix, 0, -aspectRatio, aspectRatio,
                    -1f, 1f, -1f, 1f);
        } else {
            Matrix.orthoM(mMatrix, 0, -1f, 1f, -aspectRatio, aspectRatio,
                    -1f, 1f);
        }
    }

    private int uMatrixLocation;

    @Override
    public void onDrawFrame(GL10 gl) {
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);


        //使用程序片段
        GLES30.glUseProgram(mProgram);


        uMatrixLocation = GLES30.glGetUniformLocation(mProgram, "u_Matrix");
        //正交投影矩阵
        GLES30.glUniformMatrix4fv(uMatrixLocation, 1, false, mMatrix, 0);

        aPositionLocation = GLES30.glGetAttribLocation(mProgram, "vPosition");

        //调整偏移位置 读取顶点位置
        vertexBuffer.position(0);
        //获取顶点数组 (POSITION_COMPONENT_COUNT = 2)
        GLES30.glVertexAttribPointer(aPositionLocation, POSITION_COMPONENT_COUNT, GLES30.GL_FLOAT, false, STRIDE, vertexBuffer);
        //注意：glVertexAttribPointer这个方法的第5个参数，stride，这个参数表示：
        //
        //每个顶点由size指定的顶点属性分量顺序存储。stride指定顶 点索引I和(I+1），表示的顶点数据之间的位移。如果stride为0，则每个顶点的属性数据顺序存储。如果stride大于0, 则使用该值作为获取下一个索引表示的顶点数据的跨距。
        //启用顶点属性
        GLES30.glEnableVertexAttribArray(aPositionLocation);



        GLES30.glDrawArrays(GLES30.GL_TRIANGLE_FAN, 0, floats.length / 3);
        GLES30.glDisableVertexAttribArray(aPositionLocation);

    }

}
